import pygame,sys,os

class Person(pygame.sprite.Sprite):
    def __init__(self, pos_x, pos_y):
        super().__init__()
        self.L_images = [
            pygame.image.load(self.resource_path('source/img/L_run1.png')),
            pygame.image.load(self.resource_path('source/img/L_run2.png')),
            pygame.image.load(self.resource_path('source/img/L_run3.png')),
            pygame.image.load(self.resource_path('source/img/L_run4.png'))
        ]
        self.R_images = [
            pygame.image.load(self.resource_path('source/img/R_run1.png')),
            pygame.image.load(self.resource_path('source/img/R_run2.png')),
            pygame.image.load(self.resource_path('source/img/R_run3.png')),
            pygame.image.load(self.resource_path('source/img/R_run4.png')),
        ]
        self.S_image = pygame.image.load(self.resource_path('source/img/person.png'))
        self.image = self.S_image
        self.rect = self.image.get_rect()
        self.pos_x = pos_x
        self.pos_y = pos_y
        self.rect.midbottom = (self.pos_x, self.pos_y)  # 初始位置在地面
        self.prev_rect = None  # 新增：记录上一帧的位置
        self.run = 0

        # 预加载公共音效
        pygame.mixer.init()
        self.move_sound = pygame.mixer.Sound(self.resource_path('source/sound/run.mp3'))
        self.jump_sound = pygame.mixer.Sound(self.resource_path('source/sound/jump.mp3'))
        # 设置音量
        self.move_sound.set_volume(0.1)
        self.move_channel = pygame.mixer.Channel(1)  # 专用声道
        # 跳跃音效专用声道
        self.jump_sound.set_volume(0.2)
        self.jump_channel = pygame.mixer.Channel(2)  # 新增独立声道

        self.vx = 0
        self.vy = 0
        self.alive = True

        # 动画控制
        self.animation_timer = 0
        self.current_frame = 0
        self.frame_duration = 0.08  # 0.08秒/帧

        self.gravity = 0.8
        self.jump_speed = -10
        self.speed = 5

        self.on_ground = True
        self.moving = False
        self.dire = "x"
        self.last_w_pressed = False  # 新增：记录上一次W键状态

    def check_die(self,Spikes,One_spike,Many_spike,gears):
        if  self.rect.y > 800:
            self.alive = False
        for spike in pygame.sprite.spritecollide(self,Spikes,False):
            self.alive = False
        for one_spike in pygame.sprite.spritecollide(self,One_spike,False):
            self.alive = False
        for many_spike in pygame.sprite.spritecollide(self,Many_spike,False):
            self.alive = False
        for gear in pygame.sprite.spritecollide(self,gears,False):
            self.alive = False

    def update(self, obstacles,D_obstacles):
        self.prev_rect = self.rect.copy()
        # 水平移动
        self.rect.x += self.vx

        for obstacle in pygame.sprite.spritecollide(self, obstacles, False):
            if self.vx > 0 :  # 向右碰撞
                self.rect.right = obstacle.rect.left
            elif self.vx < 0 :  # 向左碰撞
                self.rect.left = obstacle.rect.right

            self.vx = 0
            if self.on_ground:
                self.moving = False
            else:
                self.moving = True
        # 垂直移动
        self.vy += self.gravity
        self.rect.y += self.vy
        self.on_ground = False
        # 垂直碰撞检测
        for obstacle in pygame.sprite.spritecollide(self, obstacles, False):
            if self.vy > 0:  # 下落碰撞
                self.rect.bottom = obstacle.rect.top
                self.vy = 0
                self.jump_speed = -10
                self.on_ground = True
            elif self.vy < 0:  # 上升碰撞
                self.rect.top = obstacle.rect.bottom
                self.vy = 0
                self.jump_speed = -10
            # 处理动态障碍物的碰撞（区分方向）

        for obstacle in pygame.sprite.spritecollide(self, D_obstacles, False):
            overlap = self.rect.clip(obstacle.rect)
            dx = overlap.width
            dy = overlap.height
            # 优先处理较小的重叠方向
            if dx < dy:  # 水平碰撞
                if obstacle.dire=='x':
                    if self.rect.centerx < obstacle.rect.centerx:
                        self.rect.right = obstacle.rect.left
                    else:
                        self.rect.left = obstacle.rect.right
                elif obstacle.dire=='y':
                    if self.vx > 0:
                        self.rect.right = obstacle.rect.left
                    elif self.vx < 0:
                        self.rect.left = obstacle.rect.right
                self.vx = 0
            else:  # 垂直碰撞
                if obstacle.dire == 'x':
                    if self.vy > 0 :
                        self.rect.bottom = obstacle.rect.top

                        self.vy = 0
                        self.on_ground = True
                        self.jump_speed = -10
                    elif self.vy < 0  and self.rect.bottom > obstacle.rect.bottom:
                        self.rect.top = obstacle.rect.bottom
                        self.vy = 0
                        self.jump_speed = -10
                elif obstacle.dire == 'y':
                    if self.vy > 0 :  # 下落时碰撞到障碍物顶部
                        self.rect.bottom = obstacle.rect.top

                        self.vy = 0
                        if obstacle.speed<0:
                            self.jump_speed = obstacle.speed-10
                        else:
                            self.jump_speed = -10
                        self.on_ground = True
                    elif self.vy < 0  and self.rect.bottom > obstacle.rect.bottom:  # 上升时碰撞到障碍物底部
                        self.rect.top = obstacle.rect.bottom

                        self.vy = 0
                        self.jump_speed = -10

        # 屏幕检测
        self.rect.left = max(0, self.rect.left)
        self.rect.right = min(self.rect.right, 1000)
        self.rect.top = max(self.rect.top,0)

    def jump(self):
        if self.on_ground:
            self.vy = self.jump_speed
            self.jump_channel.stop()  # 停止当前可能正在播放的音效
            self.jump_channel.play(self.jump_sound)  # 使用独立声道播放
            self.on_ground = False
    def move(self, keys,dt):
        self.vx = 0  # 默认停止水平移动
        # 在移动逻辑后添加音效控制
        if keys[pygame.K_a] or keys[pygame.K_d]:
            if not self.moving :
                self.move_channel.play(self.move_sound, loops=-1)
                self.moving = True
            if keys[pygame.K_a]:
                self.speed = -5
                self.vx = self.speed * dt * 60
                self.dire = "-x"
            elif keys[pygame.K_d] :
                self.speed = 5
                self.vx = self.speed * dt * 60
                self.dire = "x"
        else:
            self.move_channel.stop()
            self.vx = 0
            self.moving = False

        # 修改跳跃逻辑：仅当按键从释放变为按下时触发
        current_w_pressed = keys[pygame.K_w]
        if current_w_pressed and not self.last_w_pressed and self.on_ground:
            self.jump()
        self.last_w_pressed = current_w_pressed  # 更新按键状态

    def check_d_wall(self,D_Walls,window):
        # 处理动态墙壁
        for d_wall in D_Walls.copy():  # 遍历副本以安全删除
            #获取人物与动态墙壁的水平距离
            horizontal_distance = abs(self.rect.centerx - d_wall.rect.centerx)
            person_bottom = self.rect.bottom
            d_wall_top = d_wall.rect.top
            d_wall_bottom = d_wall.rect.bottom
            #判断 人物的底部是否在（墙壁，墙壁加上人物高度）之间
            vertical_condition = (person_bottom <= d_wall_bottom) and (person_bottom >= d_wall_top - 100)

            if horizontal_distance < d_wall.check and vertical_condition:
                d_wall.activate()

            # 如果墙壁已销毁，从列表中移除
            if not d_wall.alive:
                D_Walls.remove(d_wall)
    def per_img(self, dt):
        if self.moving:
            self.animation_timer += dt
            if self.animation_timer >= self.frame_duration:
                self.current_frame = (self.current_frame + 1) % 4
                self.animation_timer = 0  # 重置计时器

        # 根据方向更新图片并保持对齐
        old_midbottom = self.rect.midbottom  # 始终保存当前对齐点

        if (not self.on_ground) and self.moving:
            if self.dire == "x":
                self.image = self.R_images[1]
            else:
                self.image = self.L_images[1]
        elif self.moving:
            if self.dire == "x":
                self.image = self.R_images[self.current_frame]
            else:
                self.image = self.L_images[self.current_frame]
        else:
            self.image = self.S_image
            self.current_frame = 0

        # 强制保持中下对齐
        self.rect = self.image.get_rect(midbottom=old_midbottom)

    def resource_path(self,relative_path):
        """ 根据打包后的环境动态加载资源路径 """
        if hasattr(sys, '_MEIPASS'):
            base_path = sys._MEIPASS
        else:
            base_path = os.path.abspath(".")
        return os.path.join(base_path, relative_path)


